<template>
  <div>
    <el-select style="width: 100%;" ref="selectRef" clearable popper-class="yy-cascader" @keydown.enter.native="enter"
      @visible-change="onVisibleChange" @clear="onClear" v-model="formData" :placeholder="comPlaceholder">
      <el-option :label="paramsQuery[propsLabel]" :value="paramsQuery[propsValue]" style="height: auto" disabled>
        <el-input placeholder="请输入筛选" v-model="filterValue" />
        <div ref="boxRef"></div>
      </el-option>
    </el-select>
    <el-tree v-show="false" :data="deepCloneOptions" :expand-on-click-node="false" default-expand-all v-bind="$attrs"
      ref="treeRef" highlight-current @node-click="handleNode" :node-key="propsValue" :filter-node-method="filterNode"
      :props="comDefaultProps" check-strictly />
  </div>
</template>

<script>
import { cloneDeep } from 'lodash';

export default {
  props: {
    value: {
      type: [String, Number],
      default: null,
    },
    propsLabel: {
      type: String,
      default: "label"
    },
    propsValue: {
      type: String,
      default: "value"
    },
    propsChildren: {
      type: String,
      default: "children"
    },
  },
  name: "yyCascader",
  computed: {
    formData: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit("input", val);
      },
    },
    comPlaceholder() {
      return this.$attrs.placeholder || '';
    },
    comOptions() {
      return this.$attrs.options || this.options || [];
    },
    deepCloneOptions() {
      return cloneDeep(this.comOptions)
    },
    comDefaultProps() {
      return {
        label: this.propsLabel,
        value: this.propsValue,
        children: this.propsChildren
      }
    }
  },
  watch: {
    // 侦听filterValue 的变化，调用filter的方法
    filterValue(val) {
      this.$refs.treeRef.filter(val)
    },
    comOptions: {
      handler(newVal) {
        if (newVal?.length && this.formData) {
          this.innerUpdateState();
        }
      },
      deep: true
    },
    formData: {
      handler(val) {
        if (val && this.comOptions?.length) {
          this.innerUpdateState();
        }
      },
      deep: true,
    },
  },
  data() {
    return {
      init: true,
      // 筛选框绑定的字段
      filterValue: '',
      paramsQuery: {},
    };
  },
  methods: {
    /**
     * 只在初始化时候使用
     */
    innerUpdateState () {
      if (!this.init) return;
      this.updateState();
    },
    updateState() {
      this.$nextTick(() => {
        const result = this.$refs.treeRef?.getNode(this.formData);
        if (result && result.data) {
          this.init = false;
          this.paramsQuery[this.propsLabel] = result.data[this.propsLabel];
          this.paramsQuery[this.propsValue] = result.data[this.propsValue];
          this.$emit("init", result.data);
        }
      })
    },
    onClear () {
      this.$emit('change', null);
    },
    onVisibleChange(flag) {
      if (flag) {
        // 显示了
        if (!this.$refs.boxRef.children?.length) {
          this.$refs.treeRef.$el.style.display = 'block'
          this.$refs.boxRef.appendChild(this.$refs.treeRef.$el);
        }
        this.$nextTick(() => {
          this.$refs.treeRef?.setCurrentKey(this.formData);
        })
      }
    },
    // el-tree选中发生改变触发，node为改变的数据
    handleNode(data) {
      this.init = false;
      this.paramsQuery[this.propsLabel] = data[this.propsLabel];
      this.paramsQuery[this.propsValue] = data[this.propsValue];
      this.formData = data[this.propsValue];
      this.$emit('change', data);
      this.$refs.selectRef.blur();
    },
    // 筛选事件
    filterNode(value, data) {
      if (!value) return true
      return data[this.propsLabel].indexOf(value) !== -1
    },
    enter() {
      this.$emit("enter");
    },
  },
  mounted() {
    this.init = true;
    if (this.formData && this.comOptions.length) {
      this.innerUpdateState();
    }
    this.$set(this.paramsQuery, this.propsLabel, null);
    this.$set(this.paramsQuery, this.propsValue, null);
  }
};
</script>

<style lang="scss">
.yy-cascader {
  .el-select-dropdown__item {
    background-color: #fff !important;
    cursor: default;
    font-weight: normal !important;
  }
}
</style>